Move muldiv64 out and make it as a public function.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 24 Jun 2009 09:57:00 +0000 (10:57 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 24 Jun 2009 09:57:00 +0000 (10:57 +0100)
muldiv64 is used to caculate u64*u32/u32, and we
will use it for TSC scaling.

Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/i8254.c
xen/common/lib.c
xen/include/xen/lib.h

index 2d206889bae5992078db03d234ededb2adf88c2a..a87ddecc5816206acb7477028ac859e447467798 100644 (file)
@@ -57,30 +57,6 @@ static int handle_speaker_io(
 #define get_guest_time(v) \
    (is_hvm_vcpu(v) ? hvm_get_guest_time(v) : (u64)get_s_time())
 
-/* Compute with 96 bit intermediate result: (a*b)/c */
-static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
-{
-    union {
-        uint64_t ll;
-        struct {
-#ifdef WORDS_BIGENDIAN
-            uint32_t high, low;
-#else
-            uint32_t low, high;
-#endif            
-        } l;
-    } u, res;
-    uint64_t rl, rh;
-
-    u.ll = a;
-    rl = (uint64_t)u.l.low * (uint64_t)b;
-    rh = (uint64_t)u.l.high * (uint64_t)b;
-    rh += (rl >> 32);
-    res.l.high = rh / c;
-    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
-    return res.ll;
-}
-
 static int pit_get_count(PITState *pit, int channel)
 {
     uint64_t d;
index 2f1a005ca4282a122cb258a23f23c272c313aae7..579512a4c59df39295a86af06deedbde673651f8 100644 (file)
@@ -401,6 +401,35 @@ s64 __moddi3(s64 a, s64 b)
 
 #endif /* BITS_PER_LONG == 32 */
 
+/* Compute with 96 bit intermediate result: (a*b)/c */
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+#ifdef __x86_64__
+    asm ( "mul %%rdx; div %%rcx" : "=a" (a) : "0" (a), "d" (b), "c" (c) );
+    return a;
+#else
+    union {
+        uint64_t ll;
+        struct {
+#ifdef WORDS_BIGENDIAN
+            uint32_t high, low;
+#else
+            uint32_t low, high;
+#endif            
+        } l;
+    } u, res;
+    uint64_t rl, rh;
+
+    u.ll = a;
+    rl = (uint64_t)u.l.low * (uint64_t)b;
+    rh = (uint64_t)u.l.high * (uint64_t)b;
+    rh += (rl >> 32);
+    res.l.high = rh / c;
+    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+    return res.ll;
+#endif
+}
+
 unsigned long long parse_size_and_unit(const char *s, const char **ps)
 {
     unsigned long long ret;
index 6b5033a36e7f1c668a7a2a2ad12be6901df6c5ef..bca0d65df058bb1ec25edc370d114edde6c5fcd9 100644 (file)
@@ -99,6 +99,8 @@ unsigned long long simple_strtoull(
 
 unsigned long long parse_size_and_unit(const char *s, const char **ps);
 
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
+
 #define TAINT_UNSAFE_SMP                (1<<0)
 #define TAINT_MACHINE_CHECK             (1<<1)
 #define TAINT_BAD_PAGE                  (1<<2)